package com.miyu.client1.service.magic.impl;

/**重新规划 搜索页 不再解析详细页面 提升搜索效率
 * 自定义解析流程 1；进入搜索页 获取搜索列表 2，进入列表获取 图片 书名 作者 类型 更新日期 最新章节 书籍简介 状态 等
 */

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.miyu.client1.utils.bookUtils.BookCommutils;
import org.apache.commons.lang.StringUtils;
import us.codecraft.webmagic.*;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.selector.Selectable;

import java.io.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public  class BookMagicCommon  implements PageProcessor {
    private JSONObject rs;
    private static String  regex = "\\(([^}]*)\\)";//匹配小括号
    //爬虫配置信息设置
    private Site site = new Site()
            .setCharset("utf-8")    //设置编码
            .setSleepTime(1)        //设置抓取间隔
            .setTimeOut(10000)         //设置超时时间
            .setRetrySleepTime(300)      //设置重试时间
            .setRetryTimes(3);       //设置重试次数


    public static JSONObject bookSearch (Request Str){
        JSONObject rs = new JSONObject();

        Spider.create(new BookMagicCommon()).addRequest(Str)
               // .addPipeline(new ConsolePipeline())
               // .addPipeline( new JsonFilePipeline("D:\\test\\")  )
                .addPipeline(new saveData())
                .thread(50).run();
        //    String st = readJsonFile("D:\\test\\m.lingyutxt.com\\d06e4680900fc06a5ccd863e5a8e4029.json");
        return  null;

    }
    @Override
    public void process(Page page) {
        Request request = new Request();
        String url=page.getUrl().get();//得到url，起始为http://www.147xs.org/
        //图书规则必带 根据规则解析相关内容
        JSONObject ext  = page.getRequest().getExtra("bookRule");
        String bookSearchState  = page.getRequest().getExtra("book");

        if(bookSearchState.equals("search")){
            //搜索菜单界面 取得搜索列表
            String ruleSearchList = ext.getString("ruleSearchList");//搜索页面数据列表
            //获取搜索列表元素
            List<String> bookList = page.getHtml().xpath(ruleSearchList).links().all();
            List<Selectable> charList = page.getHtml().xpath(ruleSearchList).nodes();
            //判断是否有下页 如果有下页则取下页数据
            getBookList(ext,charList,page);
            //如果有下页 取下页规则链接 再解析
/*            for (String bookUrl: bookUrlAll) {
                Request res  = new Request();
                res.putExtra("book","detail");
                res.putExtra("bookRule",ext);
                res.setUrl(bookUrl);
                page.addTargetRequest(res);
                page.setSkip(true);
            }*/
        } else if(bookSearchState.equals("detail")){
            //数据详情页面
            ext .put("bookUrl",url);
           // getContent(page);
        } else if(bookSearchState.equals("bookDetailList")){
            //数据明细 页面 取值 书籍信息 以及章节菜单 链接
            JSONObject headInfo = headInfo(page,page.getRequest().getExtra("bookRule"),page.getRequest().getExtra("bookListInfo"));
            //数据明细数据 关联规则id 判断规则来源
            headInfo.put("ruleId",ext.getString("bookId"));
            //章节列表
            List<Selectable> chapter = page.getHtml().xpath(ext.getString("ruleBookList")).nodes();
            JSONObject bookInfo  = page.getRequest().getExtra("bookListInfo");
            JSONArray ja = new JSONArray();
             for(int i=0;i<chapter.size();i++){
                 Selectable selectable = chapter.get(i);
                //章节链接
                 String contentUrl = selectable.xpath("//a").links().toString();
                 //章节名称
                 String chapterName = selectable.xpath("//a/text()").get();
                 if(contentUrl==null||contentUrl.indexOf("#")>-1)
                     continue;
                JSONObject jo = new JSONObject();
                //章节名称为空不添加
                if (StringUtils.isBlank(chapterName))
                    continue;
                 jo.put("chapterNum",i);
                 jo.put("chapterName",chapterName);
                 jo.put("chapterId", BookCommutils.getUUID());
                 jo.put("chapterSource",contentUrl);
                 jo.put("bookSource",bookInfo.getString("bookSource"));
                 jo.put("chapterContext","");
                 //增加规则来源
                 jo.put("bookRule",ext.getString("bookId"));
                 ja.add(jo);
               //  jo.put("bs",t);//判断阅读正文是否有下一页，根据匹配编码是否在此编码基础上增加如果是默认则为有下一页 ，否则跳出当前章节
             }
            //书籍正文阅读解析
            page.putField("headInfo",headInfo);
            page.putField("info",ja);
            page.putField("state","detail");

        }else if(bookSearchState.equals("context")){
            //此逻辑从新梳理 正文阅读用于只用于更新
            String  info = page.getRequest().getExtra("bookInfo").toString();
            JSONObject bookInfo = JSONObject.parseObject(info);//章节信息

            String context = page.getHtml().xpath(ext.getString("ruleChapterContent")).toString();//当前页阅读文
            bookInfo.put("chapterContext",context);
         //   String nextChapter =    page.getHtml().xpath("//*[@id='pt_next']").links().toString();//当前页的下一页
            //当前章节名称
            String chapterName = jxRulePage(page,"///div[@class='box_con']/div[@class='bookname']/h1/text()");
            //上一章链接
           String upChapter =  jxRulePage(page,"//div[@class='bottem2']/a[1]tg.lk(.@0)");
            //章节列表
            String menu = jxRulePage(page,"//div[@class='bottem2']/a[2]tg.lk(.@0)");
            //下一章链接
            String nextChapter = jxRulePage(page,"//div[@class='bottem2']/a[3]tg.lk(.@0)");
            bookInfo.put("chapterName",chapterName);
            bookInfo.put("up",upChapter);
            bookInfo.put("menu",menu);
            bookInfo.put("next",nextChapter);
            page.putField("name",bookInfo);
            getContentReg(page,bookInfo.toString());
        }else  if(bookSearchState.equals("downfile")){
            //下载数据 解析 只需要 序列 章节名称 章节内容
            JSONArray ja = new JSONArray();
            if(page.getRequest().getExtra("type").equals("1")){
                JSONObject downinfo = page.getRequest().getExtra("downinfo");

                String context = page.getHtml().xpath(ext.getString("ruleChapterContent")+"/text()").toString();//当前页阅读文
                //进入书籍正文解析
                downinfo.put("chapterContext",context);
                ja.add(downinfo);
                page.putField("info",ja);
                page.putField("state","downFile");
            }else {
                //章节列表
                List<Selectable> chapter = page.getHtml().xpath(ext.getString("ruleBookList")).nodes();
                for (int i = 0; i < chapter.size(); i++) {
                    Selectable selectable = chapter.get(i);
                    //章节链接
                    String contentUrl = selectable.xpath("//a").links().toString();
                    //章节名称
                    String chapterName = selectable.xpath("//a/text()").get();
                    if (contentUrl == null || contentUrl.indexOf("#") > -1)
                        continue;
                    JSONObject jo = new JSONObject();
                    //章节名称为空不添加
                    if (StringUtils.isBlank(chapterName))
                        continue;
                    jo.put("chapterNum", i);
                    jo.put("chapterName", chapterName);
                    jo.put("chapterContext", "");

                    Request req = new Request();
                    req.putExtra("downinfo", jo);
                    req.putExtra("book", "downfile");
                    req.putExtra("bookRule", ext);
                    req.putExtra("type", "1");
                    req.setUrl(contentUrl);
                    req.setCharset("GBK");
                    page.addTargetRequest(req);
                    page.setSkip(true);

                }

            }

        }
    }

    private JSONObject headInfo(Page page, JSONObject ext, JSONObject bookListInfo) {

    JSONObject jo = new JSONObject();
        //来源名称
        jo.put("sysSourceName",ext.getString("sysSourceName"));
        //来源规则id
        jo.put("bookRuleSource",ext.getString("bookId"));
        //来源网站
        jo.put("bookSourceRoot",ext.getString("sysSourceUrl"));
        //书名
        jo.put("ruleBookName",jxRulePage(page, ext.getString("ruleBookName")));
        //作者
        jo.put("ruleBookAuthor",jxRulePage(page, ext.getString("ruleBookAuthor")));
        //分类
        jo.put("ruleBookKind",jxRulePage(page, ext.getString("ruleBookKind")));
         //状态
        jo.put("ruleBookState",jxRulePage(page, ext.getString("ruleBookState")));
        //最后更新时间
        jo.put("ruleBookLastChapterDate",jxRulePage(page, ext.getString("ruleBookLastChapterDate")));
         //最新章节
        jo.put("ruleBookLastChapter",jxRulePage(page, ext.getString("ruleBookLastChapter")));
        //最新章节链接
        jo.put("ruleBookChapterUrl",ext.get("sysSourceUrl")+jxRulePage(page, ext.getString("ruleBookChapterUrl")));
        //简介
        jo.put("ruleBookIntroduce",jxRulePage(page, ext.getString("ruleBookIntroduce")));
         // 封面
        jo.put("ruleBookCoverUrl",jxRulePage(page, ext.getString("ruleBookCoverUrl")));

        return jo;
    }

    private void getBookList(JSONObject ext, List<Selectable> charList, Page page) {
        if (charList.size()>0){
            String bookRuleId = ext.getString("bookId");
            //来源域名
            String  bookSourceRoot = ext.getString("bookSourceUrl");
            String bookSource = ext.getString("bookUrl");
            //来源名称
            String BookSourceName = ext.getString("bookSourceName");

            //数据封装
            JSONArray ja = new JSONArray();

            for(Selectable info:charList){
                JSONObject jo = new JSONObject();
                //来源名称
                jo.put("sysSourceName",ext.getString("sysSourceName"));
                //来源规则id
                jo.put("bookRuleSource",ext.getString("bookId"));
                //来源网站
                jo.put("bookSourceRoot",ext.getString("sysSourceUrl"));
                //书名
                jo.put("ruleSearchName",jxRule(info, ext.getString("ruleSearchName")));
                //作者
                jo.put("ruleSearchAuthor",jxRule(info, ext.getString("ruleSearchAuthor")));
                //分类
                jo.put("ruleSearchKind",jxRule(info, ext.getString("ruleSearchKind")));
                //状态
                jo.put("ruleSearchBookState",jxRule(info, ext.getString("ruleSearchBookState")));
                //最后更新时间
                jo.put("ruleSearchLastChapterDate",jxRule(info, ext.getString("ruleSearchLastChapterDate")));
                //简介
                jo.put("ruleSearchIntroduce",jxRule(info, ext.getString("ruleSearchIntroduce")));
                //最新章节
                jo.put("ruleSearchLastChapter",jxRule(info, ext.getString("ruleSearchLastChapter")));
                //最新章节链接
                String  s = jxRule(info, ext.getString("ruleSearchLastChapterUrl"));
                jo.put("ruleSearchLastChapterUrl",jxRule(info, ext.getString("ruleSearchLastChapterUrl")));
               // 封面
                jo.put("ruleSearchCoverUrl",jxRule(info, ext.getString("ruleSearchCoverUrl")));
                //书链接
                jo.put("ruleSearchNoteUrl",ext.get("sysSourceUrl")+jxRule(info, ext.getString("ruleSearchNoteUrl")));
                ja.add(jo);
            }
            page.putField("state","main");
            page.putField("searchInfo",ja);
        }
    }

    private void getContentReg(Page page,String info) {
        //书籍正文阅读解析
        page.putField("info",info);
        page.putField("state","update");
    }

    /*private void getContent(Page page) {
        //书籍规则
        JSONObject ext = page.getRequest().getExtra("bookRule");

        //规则来源
        String bookRuleId =  ext.getString("bookId");

        //来源域名
        String  bookSourceRoot = ext.getString("bookSourceUrl");
        //书籍明细连接
        //判断是否有是否特殊配置 如果有 则不选取连接 否则匀取当前连接
        String bookSource="";
        if(StringUtils.isNotBlank(ext.getString("ruleBookDetailUrl")))
           bookSource = bookSourceRoot+jxRule(page,ext.getString("ruleBookDetailUrl"));
        else
            bookSource = ext.getString("bookUrl");
        //来源名称
        String BookSourceName = ext.getString("bookSourceName");
        //书名
        String bookName = jxRule(page, ext.getString("ruleSearchName"));
        //作者
        String bookAuthor = jxRule(page, ext.getString("ruleSearchAuthor"));
        //图书分类
        String bookKind = jxRule(page, ext.getString("ruleSearchKind"));

        //书籍状态
        String bookState = jxRule(page, ext.getString("ruleBookState"));
        //最后更新时间
          String bookLastDate = jxRule(page, ext.getString("ruleBookLastChapterDate"));
        //r热度
       // String bookHore = page.getHtml().xpath("//div/ul[@id='book_detail']/li[5]/text()").get();

        //书籍图片田连接
        String bookCover = jxRule(page, ext.getString("ruleSearchCoverUrl"));
        //书籍简介
        String bookDuce = jxRule(page, ext.getString("ruleSearchIntroduce"));
        //最新更新章节
        String bookLastChapter = jxRule(page, ext.getString("ruleBookLastChapter"));
        //最新更新章节连接
        String bookLastChapterUrl = jxRule(page, ext.getString("ruleBookLastChapterUrl"));
        if(bookName.trim().length()>0){
            page.putField("state","main");
            page.putField("bookRuleSource",bookRuleId);
            page.putField("BookSource",bookSource);
            page.putField("BookSourceName",BookSourceName);
            page.putField("bookName",bookName.trim());
            page.putField("bookAuthor",bookAuthor.trim()  );
            page.putField("bookKind",bookKind  );
            page.putField("bookState",bookState  );
            page.putField("bookLastDate",bookLastDate  );
            // page.putField("bookHore",bookHore  );
            page.putField("bookCover",bookSourceRoot+bookCover  );
            page.putField("bookDuce",bookDuce  );
            page.putField("bookLastChapter",bookLastChapter  );
            page.putField("bookLastChapterUrl",bookSourceRoot+bookLastChapterUrl  );
            page.putField("bookSourceRoot",bookSourceRoot);
        }

    }*/

    @Override
    public Site getSite() {
        return this.site;
    }


    //读取json文件
    public static String readJsonFile(String fileName) {
        String jsonStr = "";
        try {
            File jsonFile = new File(fileName);
            FileReader fileReader = new FileReader(jsonFile);
            Reader reader = new InputStreamReader(new FileInputStream(jsonFile), "utf-8");
            int ch = 0;
            StringBuffer sb = new StringBuffer();
            while ((ch = reader.read()) != -1) {
                sb.append((char) ch);
            }
            fileReader.close();
            reader.close();
            jsonStr = sb.toString();
            return jsonStr;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }


     //解析规则 说明
    /**
     * 规则分三段 1 正常取值  2 字符截取   3  字符替换
     * 1.使用 tg. 分割 如果只有正常取值可不加 标志符位
     * 2.字符截取规则 tg.sp(0@2) 字符取substring(0,2)取值, lp(.@1) 指 split(".")分割取 第一个 & 符 合并取值 暂不做复杂处理 tg.sp()&lp() 格式
     * 3.rp 字符替换 tg.rp(我@你) "我"替换 "你",tg.rp(#nbsp@"") 去空格
     * //li[@class='author']/a/text()tg.sp(0@3)&lp(:@1)tg.rp(#nbsp@"")
     *  增加href 取值规则 tg.lk(.@0) 最后取链接 ()取值第几个链接 默认 0 链接默认最后取值 不做分割数据
     */
        private String jxRule(Selectable page ,String ruleStr){
            String rs = "";
            if(StringUtils.isNotBlank(ruleStr)){
                String [] tg = ruleStr.split("tg.");
                if(tg.length>0){
                     rs =  page.xpath(tg[0]).get();
                    for (int i = 1; i < tg.length; i++) {
                        String [] sa = tg[i].split("&");
                        for (String str:sa){
                            if(str.indexOf("lk")>-1){
                                Selectable st = page.xpath(tg[0]);
                                 return   rs = regLink(st,page,str);
                            }

                            rs =  reg(rs,str);
                        }
                    }
                }else {
                    rs =  page.xpath(ruleStr).get();
                }

            }
            return  rs;
        }

    /**
     * 参数page
     * @param page
     * @param ruleStr
     * @return
     */
    private String jxRulePage(Page page ,String ruleStr){
        String rs = "";
        if(StringUtils.isNotBlank(ruleStr)){
            String [] tg = ruleStr.split("tg.");
            if(tg.length>0){
                rs =  page.getHtml().xpath(tg[0]).get();
                for (int i = 1; i < tg.length; i++) {
                    String [] sa = tg[i].split("&");
                    for (String str:sa){
                        if(str.indexOf("lk")>-1){
                            Selectable st = page.getHtml().xpath(tg[0]);
                            return rs = regLinkPage(st,page,str);
                        }

                        rs =  reg(rs,str);
                    }
                }
            }else {
                rs =  page.getHtml().xpath(ruleStr).get();
            }

        }
        return  rs;
    }

    private String regLinkPage(Selectable ob, Page page, String str) {
        String rs = "";
        //取括号内容 之后再分割 取值
        Pattern compile = Pattern.compile(regex);
        Matcher matcher = compile.matcher(str);
        String group="";

        while(matcher.find()){
            group = matcher.group(1);
            String [] s = group.split("@");
            if(str.indexOf("lk")>-1){
                if(s.length>1)
                    rs =  ob.xpath("//a").links().get();
                    // rs = ob.replace(s[0],s[1]);
                else
                    rs = ob.toString();
            }
        }
        return  rs;
    }

    private String regLink(Selectable ob, Selectable page, String str) {
        String rs = "";
        //取括号内容 之后再分割 取值
        Pattern compile = Pattern.compile(regex);
        Matcher matcher = compile.matcher(str);
        String group="";

        while(matcher.find()){
            group = matcher.group(1);
            String [] s = group.split("@");
            if(str.indexOf("lk")>-1){
                if(s.length>1)
                   rs =  ob.xpath("//a").links().get();
                   // rs = ob.replace(s[0],s[1]);
                else
                    rs = ob.toString();
            }
        }
        return  rs;
    }


    private String reg(String ob ,String str){
            String rs = ob;
            //取括号内容 之后再分割 取值
            Pattern compile = Pattern.compile(regex);
            Matcher matcher = compile.matcher(str);
            String group="";

            while(matcher.find()){
                 group = matcher.group(1);
            }
            String [] s = group.split("@");
            if(str.indexOf("sp")>-1){
                if(s.length>1)
                    rs = ob.substring(Integer.valueOf(s[0]),Integer.valueOf(s[1]));
                else
                    rs = ob.substring(Integer.valueOf(s[0]),ob.length());
            }else if(str.indexOf("lp")>-1){
                if(s.length>1)
                    if(ob.split(s[0]).length>1)
                         rs = ob.split(s[0])[Integer.valueOf(s[1])];
                else
                    rs = ob;
            }else if(str.indexOf("rp")>-1){
                if(s.length>1)
                     rs = ob.replace(s[0],s[1]);
                else
                    rs = ob;
            }else if(str.indexOf("lk")>-1){
                if(s.length>1)
                    rs = ob.replace(s[0],s[1]);
                else
                    rs = ob;
            }
            return  rs;
        }
}
